/* Copyright (c) 2006, 2009, Carl Burch. License information is located in the
 * com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */
 
package com.cburch.logisim.tools;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import com.cburch.logisim.comp.ComponentFactory;
import com.cburch.logisim.util.ListUtil;

/**
 * Abstract class that organizes similar tools and components.
 */
public abstract class Library {
	
	/**
	 * Get the name of the library.
	 *
	 * @return	String		the name of the library
	 */
    public String getName() {
        return getClass().getName();
    }

	/**
	 * Get a list containing the tools in the library.
	 *
	 * @return	List		a list of the tools in the library
	 */
    public abstract List getTools();

	/**
	 * Get the String representation of the library.
	 *
	 * @return	String		string representation of the library
	 */
    public String toString() { return getName(); }

	/**
	 * Get the name of the library object.
	 *
	 * @return	String		the name of the library
	 */
    public String getDisplayName() { return getName(); }
    
	/**
	 * Check if the object is "dirty" (find out what dirty means).
	 *
	 * @return	boolean		whether the library is dirty or not
	 */
    public boolean isDirty() { return false; }

	/**
	 * Get a list of sub-libraries in this library.
	 *
	 * @return	List		list of libraries
	 */
    public List getLibraries() {
        return Collections.EMPTY_LIST;
    }

	/**
	 * Get the sub-libraries and tools contained in the library.
	 *
	 * @return	List		list of tools and libraries contained in the library
	 */
    public List getElements() {
        return ListUtil.joinImmutableLists(getTools(), getLibraries());
    }

	/**
	 * Searches for a tool object with the given name in the library. Returns the tool
	 * if found and null otherwise.
	 *
	 * @param	String		name of the tool to search for 
	 * @return	Tool		the matched tool, null if tool not found
	 */
    public Tool getTool(String name) {
        Iterator it = getTools().iterator();
        while(it.hasNext()) {
            Object o = it.next();
            if(o instanceof Tool && ((Tool) o).getName().equals(name)) {
                return (Tool) o;
            }
        }
        return null;
    }

	/**
	 * Checks if the given tool shares a source with any tools in the
	 * tool list.
	 *
	 * @param	Tool		the tool that might share a source with a tool in the tool list
	 * @return	boolean		whether the query tool shares a source with a tool in the library
	 */
    public boolean containsFromSource(Tool query) {
        for(Iterator it = getTools().iterator(); it.hasNext(); ) {
            Object obj = it.next();
            if(obj instanceof Tool) {
                Tool tool = (Tool) obj;
                if(tool.sharesSource(query)) {
                    return true;
                }
            }
        }
        return false;
    }
    
	/**
	 * Searches for a tool in the given library and returns the index of
	 * the tool in the tool list if found and -1 otherwise.
	 *
	 * @param	ComponentFactory		tool object that to be searched for 
	 * @return	int		index of the found tool in the library, -1 if not found
	 */
    public int indexOf(ComponentFactory query) {
        int index = 0;
        for(Iterator it = getTools().iterator(); it.hasNext(); index++) {
            Object obj = it.next();
            if(obj instanceof AddTool) {
                AddTool tool = (AddTool) obj;
                if(tool.getFactory() == query) return index;
            }
        }
        return -1;
    }
    
	/**
	 * Checks if a tool object is contained in the library.
	 *
	 * @param	ComponentFactory		tool object that is to be searched for 
	 * @return	boolean		whether the component is found
	 */
    public boolean contains(ComponentFactory query) {
        return indexOf(query) >= 0;
    }

	/**
	 * Searches for a sub-library with the given name in the library. Returns
	 * the index of the library in the library list if found and -1 otherwise.
	 *
	 * @param	String		name of sub-library that is to be searched for 
	 * @return	Library		the library searched for, null if not found
	 */
    public Library getLibrary(String name) {
        Iterator it = getLibraries().iterator();
        while(it.hasNext()) {
            Object o = it.next();
            if(o instanceof Library && ((Library) o).getName().equals(name)) {
                return (Library) o;
            }
        }
        return null;
    }

}
